/*
 * File     : SizedBufferStructureField.java
 * Created  : 17 Nov 2011
 *
 * Copyright © 2011 Matthew Wilson (mj. {my-surname} .uk {at} gmail.com)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.googlecode.dni.internal.structure;

import static com.googlecode.dni.internal.DniTypes.STRUCTURE_HELPER_TYPE;

import java.lang.reflect.Method;
import java.nio.Buffer;

import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

import com.googlecode.dni.type.structure.IllegalStructureException;


/**
 * Encapsulates details of a pointer to primitive structure's field used during
 * class generation.
 *
 * @author Matthew Wilson
 */
final class SizedBufferStructureField extends AbstractBufferStructureField
{

    /**
     * {@inheritDoc}
     */
    @Override
    void setGetter( final Method getter )
    {
        super.setGetter( getter );

        if ( !isSized() )
        {
            throw new IllegalStructureException( "Getter with buffer can only be used with @FixedSize or @DynamicSize: " + getter );
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    void writeGetter( final MethodVisitor methodVisitor,
                      final String implName )
    {
        writeGetPointer( methodVisitor );
        POINTER.writeGet( methodVisitor, true );

        writeGetSize( methodVisitor, implName, getBufferUnitSize() );

        methodVisitor.visitMethodInsn( Opcodes.INVOKESTATIC,
                                       STRUCTURE_HELPER_TYPE,
                                       "getSized" + getBufferType().getSimpleName(),
                                       "(JI)" + Type.getDescriptor( getBufferType() ) );

        methodVisitor.visitInsn( Opcodes.ARETURN );
    }

    /** {@inheritDoc} */
    @Override
    Class< ? extends Buffer > initBufferType( final Method getter )
    {
        return getter.getReturnType().asSubclass( Buffer.class );
    }

}
